package com.ccp.dev.workflow.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.Dom4jUtil;
import com.ccp.dev.core.util.XmlBeanUtil;
import com.ccp.dev.system.util.XmlUtil;
import com.ccp.dev.workflow.dao.PersonScriptDao;
import com.ccp.dev.workflow.model.PersonScript;
import com.ccp.dev.workflow.xml.PersonScriptXml;
import com.ccp.dev.workflow.xml.PersonScriptXmlList;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassDescribe:系统人员脚本 Service类
 * @author :fanruiqi
 * Date: 2019-07-18
 * Since:1
 */
@Service
public class PersonScriptService extends BaseService<PersonScript> {
    @Resource
    private PersonScriptDao personScriptDao;

    /**
     * 导入人员脚本XML
     * @param inputStream
     * @throws Exception
     */
    public void importXml(InputStream inputStream) throws Exception {
        Document doc = Dom4jUtil.loadXml(inputStream);
        Element root = doc.getRootElement();
        // 验证格式是否正确
        XmlUtil.checkXmlFormat(root, "system", "personScripts");

        String xmlStr = root.asXML();
        PersonScriptXmlList personScriptXmlList = (PersonScriptXmlList) XmlBeanUtil
                .unmarshall(xmlStr, PersonScriptXmlList.class);

        List<PersonScriptXml> list = personScriptXmlList.getPersonScriptXml();

        for (PersonScriptXml personScriptXml : list) {
            // 导入表，并解析相关信息
            importPersonScriptXml(personScriptXml);

        }

    }

    /**
     * 导入时生成人员脚本
     * @param personScriptXml
     * @throws Exception
     */
    private void importPersonScriptXml(PersonScriptXml personScriptXml)throws Exception {
        PersonScript personScript = personScriptXml.getPersonScript();
        if (BeanUtils.isEmpty(personScript)) {
            throw new Exception();
        }
        personScript.setId(UUIDUtils.getUUIDFor32());
        personScriptDao.add(personScript);
    }

    /**
     * 导出全部人员脚本
     * @param personScriptList
     * @return
     * @throws Exception
     */
    public String exportXml(List<PersonScript> personScriptList) throws Exception{
        PersonScriptXmlList personScriptXmlList =new PersonScriptXmlList();
        List<PersonScriptXml> xmlList   =   new ArrayList<PersonScriptXml>();
        for(PersonScript script:personScriptList){
            PersonScriptXml scriptXml = exportPersonScriptXml(script);
            xmlList.add(scriptXml);
        }
        personScriptXmlList.setPersonScriptXml(xmlList);
        return XmlBeanUtil.marshall(personScriptXmlList,PersonScriptXmlList.class);
    }

    /**
     * 导出人员脚本XML
     * @param tableIds
     * @return
     * @throws Exception
     */
    public String exportXml(String[] tableIds) throws Exception {
        PersonScriptXmlList personScriptXmlList = new PersonScriptXmlList();
        List<PersonScriptXml> xmlList   =   new ArrayList<PersonScriptXml>();
        for(String tableId:tableIds){
            PersonScript script = personScriptDao.getById(tableId);
            PersonScriptXml scriptXml = exportPersonScriptXml(script);
            xmlList.add(scriptXml);
        }
        personScriptXmlList.setPersonScriptXml(xmlList);
        return XmlBeanUtil.marshall(personScriptXmlList,PersonScriptXmlList.class);
    }

    /**
     * 导出信息
     * @param personScript
     * @return
     */
    private PersonScriptXml exportPersonScriptXml(PersonScript personScript) {
        PersonScriptXml personScriptXml = new PersonScriptXml();
        String id = personScript.getId();
        if(BeanUtils.isNotIncZeroEmpty(id)){
            //导出人员脚本
            personScriptXml.setPersonScript(personScript);
        }
        return personScriptXml;
    }

    /**
     * 查询所有有效的人员脚本
     * @return
     */
    public List<PersonScript> queryPersonScript() {
        return personScriptDao.queryPersonScript();
    }

    /**
     * 通过类名获取类的所有方法
     * @param name 类名
     * @return
     * @throws Exception
     */
    public JSONArray getMethodsByName(String name) throws Exception{
        JSONArray jsonArray = new JSONArray();
        Class<?> t = Class.forName(name);
        Method[] methods = t.getDeclaredMethods();
        for(Method method : methods){
            String returnType = method.getReturnType().getCanonicalName();

            if(!"Set<String>".equals(returnType) && !"java.util.Set".equals(returnType)){ continue;}
            Integer modifirer = method.getModifiers();

            if(modifirer!=1){continue;}
            JSONObject jsonObjectMethod = new JSONObject();
            JSONArray  jsonArrayPara    = new JSONArray();
            Class<?>[] paraArr  =   method.getParameterTypes();
            for(int i=0;i<paraArr.length;i++){
                Class<?> para = paraArr[i];
                String paraName = "arg" + i;
                String paraType = para.getCanonicalName();
                jsonArrayPara.add(new JSONObject().accumulate("paraName", paraName)
                        .accumulate("paraType", paraType)
                        .accumulate("paraDesc", ""));
            }
            jsonObjectMethod.accumulate("returnType", returnType)
                    .accumulate("methodName", method.getName())
                    .accumulate("para", jsonArrayPara);
            jsonArray.add(jsonObjectMethod);
        }
        return jsonArray;
    }

    /**
     * 验证脚本是否有效
     * @return msg字符串
     */
    public String validScriptIsEnable() {
        Boolean hasUnEnable = false;
        List<PersonScript> list = personScriptDao.queryList(null);
        if(BeanUtils.isEmpty(list)){
            return  "script.invalid";
        }else{
            Class<?> t = null;
            for(PersonScript script : list){
                try{
                    t = Class.forName(script.getClassName());
                    String paraStr = script.getArgument();
                    JSONArray jarry = JSONArray.fromObject(paraStr);
                    Integer size = jarry.size();
                    Class<?>[] paras = new Class<?>[size];
                    for(int i=0;i<size;i++){
                        JSONObject jobject = jarry.getJSONObject(i);
                        paras[i] = Class.forName(jobject.getString("paraType"));
                    }
                    Method method = t.getMethod(script.getMethodName(), paras);
                    String returnTypeStr = method.getReturnType().getCanonicalName();
                    if(!"Set<String>".equals(returnTypeStr)&&!"java.util.Set".equals(returnTypeStr)){
                        throw new Exception("返回值不是Set<String>类型");
                    }
                    if(method.getModifiers()!=1){
                        throw new Exception("方法不是public类型");
                    }
                }
                catch(Exception ex){
                    hasUnEnable = true;
                    script.setEnable(1);
                    personScriptDao.update(script);
                }
            }
            if(hasUnEnable) {
                return  "script.valid.failure";
            }else {
                return  "script.valid.success";
            }
        }
    }
}
